package com.yigerende.service.impl;

import com.yigerende.dao.CommentRepository;
import com.yigerende.model.Comment;
import com.yigerende.service.CommentService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class CommentServiceImpl implements CommentService {


    @Autowired
    private CommentRepository commentRepository;

    //通过博客id查询到对应的所有评论
    @Override
    public List<Comment> listCommentByBlogId(Long blogId) {
        //创建时间倒序排序
        Sort sort = Sort.by(Sort.Direction.ASC,"createTime");
        List<Comment> comments = commentRepository.findByBlogIdAndParentCommentNull(blogId,sort);
        return eachComment(comments);
    }


    //把用户输入的信息保存到数据库
    @Transactional//这个方法放到一个事物里面（值刷新部分区域放到事物里面）
    @Override
    public Comment saveComment(Comment comment) {
        //先要判断这个用户的评论有没有父级（到底是回复的还是直接评论的）
        //默认parentCommentId为-1没有父级
        Long parentCommentId = comment.getParentComment().getId();//取到这个值进行判断

        //不等于-1的话，就说明用户是点击了回复的评论
        if(parentCommentId != -1){
            //通过id找到父级的评论,然后又传递给comment评论模型里面，现在评论模型里面就有父级评论和子级评论
            comment.setParentComment((Comment) commentRepository.findById(parentCommentId).get());
        }else {//等于-1就为父级评论
            comment.setParentComment(null);//就把是否有父级设置为空传递给数据库
        }
        //给一个创建时间
        comment.setCreateTime(new Date());
        //然后又把comment评论模型放入数据库
        return (Comment) commentRepository.save(comment);
    }



/**
 *
 * 总归的顺序是：
 * 1.找到所有的评论
 * 2.通过双for循环，把每一个顶级评论的二级子类评论找到进行传递
 * 3.把每一个二级子类评论再传递回去
 * */

    /**
    * 循环每个顶级的评论节点（就是最上面那一个）
    * */
    private  List<Comment> eachComment(List<Comment> comments){
        //comments数据库对应博客的所有评论都拿过来了
        //创建一个新的集合，避免，数据库数据变动
        List<Comment> commentsView = new ArrayList<>();
        for (Comment comment : comments){
            Comment c = new Comment();
            //把数据库相同的都给了comment，保留数据库原有的
            BeanUtils.copyProperties(comment,c);
            //把全部数据又放到了commentsView这个里面，这个里面有所有的评论信息
            commentsView.add(c);
        }
        //合并评论的各层子代到第一级子代(第二代)集合中
        combineChildren(commentsView);
        return commentsView;
    }

    /**
    * root根节点，blog不为空的对象集合
    * */
    private void combineChildren(List<Comment> comments){
            //comments还是上面传递过来的对应博客的所有评论都拿过来了
        for (Comment comment : comments){
            //ReplyComments评论模型里面的子类拿到
            //这样就拿到了每一个子类
            List<Comment> replys1 = comment.getReplyComments();
            for (Comment reply1 : replys1){
                /**
                 * 循环迭代，找出子代，存放在tempReplys中
                 * 把二级子类给循环找出，后面的所有子类评论
                 */
                recursively(reply1);
            }
            //修改顶级节点的reply集合为迭代处理后的集合
            comment.setReplyComments(tempReplys);//把所有的二级评论和后面的所有评论都放在comment里面子级(ReplyComments)评论了
            //清楚临时存放区
            tempReplys = new ArrayList<>();
        }
    }


    //存放迭代找出的所有子代的集合，临时存放
    /**
     * 二级评论下面所有的评论都放到这个集合里面
     * */
    private List<Comment> tempReplys = new ArrayList<>();

    /*
    * 二级子类评论后面所有的评论
    * 上面传递过来二级子类
    * */
    private void recursively(Comment comment){
        //把传过来的二级子类评论的头存放在临时存放的集合里面
        tempReplys.add(comment);
        if (comment.getReplyComments().size()>0){//每个父级评论如果有子类评论的话（长度就大于0）
            //把子级评论拿出来进行循环,找到所有二级评论下面的所有评论
            List<Comment> replys = comment.getReplyComments();
            for (Comment reply : replys){
                tempReplys.add(reply);
                if (reply.getReplyComments().size()>0){//再进行判断这个评论里面还有没有评论（有的话再重复调用这个方法）
                    recursively(reply);
                }
            }
        }

    }

}
